-
Notifications
You must be signed in to change notification settings - Fork 339
Implementing Firebase SDK Initialization and Custom Authentication #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
hiranya911
commented
Mar 20, 2017
- First iteration of the firebase.App and firebase.auth APIs. These enable the user to initialize the SDK (i.e. create an instance of firebase.App) from a certificate credential, and use it to create custom auth tokens, and verify ID tokens signed by Firebase backend servers.
- Unit tests (executable via pytest)
- Pylint integration for checking code quality
- Initial documentation on running unit tests and using pylint
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good so far! I very briefly skimmed the actual source and test files. If I should take a closer look because things changed drastically, please let me know.
@@ -0,0 +1,410 @@ | |||
[MASTER] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it safe to assume this was copied from some Google internal .pylintrc
file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Google's internal configuration has a bunch of Google specific commands and directives that pylint cannot recognize. So I took the default config used by pylint, and slightly modified it to match some of our internal requirements (e.g. disabling reports, line length 80 etc.). Generally speaking this version of .pylintrc is even more stricter than what we use internally. We can use it for a while and relax some of the constraints to fit our needs in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, thanks for clarifying.
.pylintrc
Outdated
[FORMAT] | ||
|
||
# Maximum number of characters on a single line. | ||
max-line-length=80 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you feel about this? One of my biggest frustrations with google3 is the very small line lengths. I've been using 120 in the Admin Node.js SDK, but even 100 is better than 80. Now that we aren't in google3, we can tailor this to what we like. If 80 is what you prefer, we can of course keep it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer something higher as well. Lets go with 100. That's what pylint recommends by default. I'll just change the pylint config for now. I'll send another PR with the source files reformatted.
README.md
Outdated
@@ -1,2 +1,84 @@ | |||
# Firebase Admin Python SDK | |||
|
|||
Firebase Admin Python SDK enables server-side (backend) Python developers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add "The" to the beginning of this sentence.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
README.md
Outdated
@@ -1,2 +1,84 @@ | |||
# Firebase Admin Python SDK | |||
|
|||
Firebase Admin Python SDK enables server-side (backend) Python developers | |||
to integrate [Firebase](http://firebase.google.com) into their services |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/http/https
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
README.md
Outdated
Firebase Admin Python SDK enables server-side (backend) Python developers | ||
to integrate [Firebase](http://firebase.google.com) into their services | ||
and applications. Currently this SDK provides Firebase custom authentication | ||
support. Other Firebase APIs will be added soon. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's drop this last sentence. If there's one thing I've learned, it's always better to under-promise and over-deliver :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
README.md
Outdated
|
||
``` | ||
./lint.sh | ||
./lint.sh all |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion to aide those who skim docs:
./lint.sh # Lint locally modified source files
./lint.sh all # Lint all source files
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -1,2 +1,84 @@ | |||
# Firebase Admin Python SDK |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is some great info here! I think in the long-term, we are going to want to have the README
be more of a short description of what the project is, how to install and use it, link to the release notes, and links to the relevant documentation. The info on running tests and linting will move in the .github/CONTRIBUTION.md
file since most people wont' need that info up front. This is how the Admin Node.js SDK and a lot of our existing open source projects are structured. This can be done in a follow-up PR though and we probably should come up with a common template of sorts to share amongst the Admin SDK repos.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack
@@ -0,0 +1,157 @@ | |||
"""Firebase Admin SDK for Python.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not reviewing the source and test files that closely since I assume they are mostly copy-pasted. If there are important differences, please call them out for me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sources haven't changed at all. But I've reimplemented the tests using pytest (as opposed to unittest). Pytest is a lot more flexible and powerful. Some of the other open source libraries (e.g. oauth2client) have also switched to it.
With pytest our test sources became shorter by about 100 lines, while giving us more test cases than we had :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome! I gave the tests a closer look then since the code changed in a non-trivial way.
tests/data/private_key.pem
Outdated
@@ -0,0 +1,28 @@ | |||
-----BEGIN PRIVATE KEY----- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we okay checking this private key into the repo? This will be public, so we need to make sure this doesn't actually give anyone access to anything. Ideally we can just use mocked private keys, which is what I did in the Admin Node.js SDK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I replaced this with the private key at https://github.com/firebase/firebase-admin-node/blob/master/test/resources/mock.key.json
Had to generate a self-signed cert for it to update public_certs.json
@@ -0,0 +1,12 @@ | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto on my message above about the private key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Used the mock private key as above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, thanks! I know this is a bit picky, but can we also switch out project_id
, client_email
, client_id
, and client_x509_cert_url
with clearly mock values (e.g. "mock-project-id"
, "mock-email@mock-project-id.iam.gserviceaccount.com"
, "1234567890"
, and "https://www.googleapis.com/robot/v1/metadata/x509/mock-emai%40mock-project-id.iam.gserviceaccount.com")?
… private key from Node SDK tests for testing
Made the suggested changes. Please take a look at the test sources, since they underwent some changes during migration to pytest. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, I'm really happy with how this is coming along! I took a deeper dive into the new tests and had some cleanup suggestions. So, back to you for another round.
@@ -0,0 +1,410 @@ | |||
[MASTER] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, thanks for clarifying.
@@ -0,0 +1,157 @@ | |||
"""Firebase Admin SDK for Python.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome! I gave the tests a closer look then since the code changed in a non-trivial way.
@@ -0,0 +1,12 @@ | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, thanks! I know this is a bit picky, but can we also switch out project_id
, client_email
, client_id
, and client_x509_cert_url
with clearly mock values (e.g. "mock-project-id"
, "mock-email@mock-project-id.iam.gserviceaccount.com"
, "1234567890"
, and "https://www.googleapis.com/robot/v1/metadata/x509/mock-emai%40mock-project-id.iam.gserviceaccount.com")?
tests/test_app.py
Outdated
@pytest.mark.parametrize('name', invalid_names) | ||
def test_app_get_with_invalid_name(self, name): | ||
with pytest.raises(ValueError): | ||
firebase.initialize_app(OPTIONS, name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be get_app()
, not initialize_app()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
|
||
class TestFirebaseApp(object): | ||
"""Test cases for App initialization and life cycle.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we don't have tests for delete_app()
. Can you add them in this PR or put together a follow-up PR for it? I know the API might be changing according to our API proposal, so it's fine to push this to a later PR to avoid throw-away work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good. I'll add it in a future PR. I will have to send another PR anyway to implement the changes proposed in the API proposal.
tests/test_auth.py
Outdated
'kid': 'd98d290613ae1468f7e5f5cf604ead38ca9c8358' | ||
} | ||
payload = { | ||
'aud': 'mg-test-1210', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we pull these dynamically from tests/data/service_account.json
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Replaced with CREDENTIAL.project_id
tests/test_auth.py
Outdated
return AuthFixture(request.param) | ||
|
||
@pytest.fixture | ||
def non_cert_app(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't seem to wrap my head around how this works. Can you add a comment explaining what this is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added some docstrings explaining what's going on here.
tests/test_auth.py
Outdated
id_token = get_id_token() | ||
gcloud_project = os.environ.get(auth.GCLOUD_PROJECT_ENV_VAR) | ||
try: | ||
os.environ[auth.GCLOUD_PROJECT_ENV_VAR] = 'mg-test-1210' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull project ID dynamically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
tests/test_auth.py
Outdated
def test_no_project_id(self, non_cert_app): | ||
id_token = get_id_token() | ||
gcloud_project = None | ||
if os.environ.has_key(auth.GCLOUD_PROJECT_ENV_VAR): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this block could be slightly cleaned up:
gcloud_project = os.environ.get(auth.GCLOUD_PROJECT_ENV_VAR)
if gcloud_project:
del os.environ[auth.GCLOUD_PROJECT_ENV_VAR]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
tests/test_auth.py
Outdated
'iat': int(time.time()) - 100, | ||
'exp': int(time.time()) + 3600, | ||
'sub': '1234567890', | ||
'uid': USER, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically ID tokens do not have a uid
claim, so I think we should drop it in this test fixture. It also means we need to add code in the future to explicitly copy the sub
claim to the uid
claim and add a test to ensure this happens.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Removed the uid claim, and updated the affected test cases to not look for it. We will update those test cases once we implement this claim copy functionality.
All comments addressed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Back to you to merge. Let's see if the Jenkins job to sync repos works...